package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.ReadDoTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.threadlocal.CommonGlobalParamSetHandle;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.*;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpProcessInstanceHandleRelDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpReadDoUsersDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.TaskCandidateQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
　　* @description: 用户信息处理句柄
　　* @author shenrm
　　* @date 2021/11/9 20:01
　　*/
@Component
public class UserInfoHandleProcessor {

    /**
     * 日志类
     */
    private Logger LOGGER = LoggerFactory.getLogger(UserInfoHandleProcessor.class);

    private static final String SPLITCHAR = ",";

    @Autowired
    private UserService userService;

    @Autowired
    private UserOrgService userOrgService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserPositionService userPositionService;

    @Autowired
    private UserGroupService userGroupService;

    /**
     * 组装任务候选人查询条件
     *
     * @param taskCandidateQueryVo
     * @param userCode
     */
    public void convertCandidateQueryVo(TaskCandidateQueryVo taskCandidateQueryVo, String userCode) {
            if (Objects.isNull(taskCandidateQueryVo) ||
                StringUtils.isBlank(userCode)) {
                return;
            }

            // 获取用户信息
            User userInfo = userService.getFullUserInfo(userCode);
            if (Objects.isNull(userInfo)) {
                LOGGER.error(String.format("根据userId[%s]查询用户信息为空", userCode));
                return;
            }

            // 设置用户编码
            taskCandidateQueryVo.setUserCode(userCode);
            // 设置组织
            taskCandidateQueryVo.setOrgCodes(this.convertCodesToStr(userInfo.getOrgInfos(), "ORG"));
            // 设置角色
            taskCandidateQueryVo.setRoleCodes(this.convertCodesToStr(userInfo.getRoleInfos(), "ROLE"));
            // 设置用户组
            taskCandidateQueryVo.setGroupCodes(this.convertCodesToStr(userInfo.getGroupInfos(), "GROUP"));
            // 设置岗位
            taskCandidateQueryVo.setPositionCodes(this.convertCodesToStr(userInfo.getPositionInfos(), "POSITION"));
        }

    /**
     *
     * @param dataList
     * @param type
     * @return
     */
    public String convertCodesToStr(List dataList, String type) {
        if(CollectionUtils.isEmpty(dataList)) {
            return "";
        }

        StringBuilder sbl = new StringBuilder("");
        switch (type) {
            case "ROLE":
                List<RoleInfo> roleInfos = dataList;
                for (RoleInfo roleInfo:roleInfos) {
                    sbl.append(roleInfo.getRoleCode()).append(SPLITCHAR);
                }
                break;
            case "ORG":
                List<OrgInfo> orgInfos = dataList;
                for (OrgInfo orgInfo:orgInfos) {
                    sbl.append(orgInfo.getOrgCode()).append(SPLITCHAR);
                }
                break;
            case "GROUP":
                List<GroupInfo> groupInfos = dataList;
                for (GroupInfo groupInfo:groupInfos) {
                    sbl.append(groupInfo.getGroupCode()).append(SPLITCHAR);
                }
                break;
            case "POSITION":
                List<PositionInfo> positionInfos = dataList;
                for (PositionInfo positionInfo:positionInfos) {
                    sbl.append(positionInfo.getPositionCode()).append(SPLITCHAR);
                }
                break;
            default:
                break;
        }
        return sbl.deleteCharAt(sbl.length() -1).toString();
    }

    /**
     * 检查是否需要设置用户变量信息
     *
     * @param user
     */
    public void checkSetUserVarInfo(User user) {
        // 获取单个线程全局设置的用户信息
        User userInfo = CommonGlobalParamSetHandle.getUser();
        // 为空时在该方法前再设置一次,否则,再调用flowable底层保存任务触发监听事件之后还会调用其它方法导致getCurrentUser时报错
        if(Objects.isNull(userInfo)) {
            CommonGlobalParamSetHandle.setUser(user);
        }
    }

    /**
     * 解析用户信息集合
     *
     * @param readCopyTos
     * @param orgCodes
     * @param roleCodes
     * @param positionCodes
     * @param groupCodes
     * @return
     */
    public List<UserInfo> resolveUserInfoList(List<String> readCopyTos, List<String> orgCodes,
                                          List<String> roleCodes, List<String> positionCodes,
                                          List<String> groupCodes) {
        // 人员列表集合
        List<UserInfo> userInfos = new ArrayList<>();
        // 用户组织编码不为空
        if(CollectionUtils.isNotEmpty(readCopyTos)) {
            List<UserInfo> readCopyToList = readCopyTos.stream().map(readCopyTo -> {
                UserInfo userInfo = new UserInfo();
                userInfo.setUserCode(String.valueOf(readCopyTo));
                return userInfo;
            }).collect(Collectors.toList());
            // 添加到集合中
            userInfos.addAll(readCopyToList);
        }

        // 用户组织编码不为空
        if(CollectionUtils.isNotEmpty(orgCodes)) {
            List<UserInfo> userOrgInfos = userOrgService.getUserListByOrg(orgCodes);
            userInfos.addAll(userOrgInfos);
        }

        // 用户角色编码不为空
        if(CollectionUtils.isNotEmpty(roleCodes)) {
            List<UserInfo> userRoleInfos = userRoleService.getUserListByRoleIdList(roleCodes);
            userInfos.addAll(userRoleInfos);
        }

        // 用户岗位编码不为空
        if(CollectionUtils.isNotEmpty(positionCodes)) {
            List<UserInfo> userPositionInfos = userPositionService.getUserListByPositionCodes(positionCodes);
            userInfos.addAll(userPositionInfos);
        }

        // 创建用户组编码long数据集合
        List<Long> groupCodeLongs = new ArrayList<>();
        // 用户组编码不为空
        if(CollectionUtils.isNotEmpty(groupCodes)) {
            for (String groupCode : groupCodes){
                groupCodeLongs.add(Long.parseLong(groupCode));
            }
            // 根据用户组编码long数据集合查询获取数据
            List<UserInfo> userGroupInfos = userGroupService.getUserListByGroupId(null, groupCodeLongs);
            userInfos.addAll(userGroupInfos);
        }
        return userInfos;
    }


    /**
     * 解析阅办人员或其它关联信息
     *
     * @param dto
     * @return
     */
    public Map<String, List<String>> resolveReadDoUsers(HttpProcessInstanceHandleRelDto dto) {
        List<HttpReadDoUsersDto> readDoUsers = dto.getReadDoUsers();
        if(CollectionUtils.isEmpty(readDoUsers)) {
            return null;
        }
        Map<String, List<String>> readDoDataMap = new HashMap<>();

        // 阅办人ID集合
        List<String> readCopyTos = new ArrayList<>();

        // 阅办人所属组织集合
        List<String> orgCodes = new ArrayList<>();

        // 阅办人所属角色集合
        List<String> roleCodes = new ArrayList<>();

        // 阅办人所属用户组集合
        List<String> groupCodes = new ArrayList<>();

        // 阅办人所属岗位集合
        List<String> positionCodes = new ArrayList<>();
        for (HttpReadDoUsersDto readDoUserDto:readDoUsers) {
            String type = readDoUserDto.getType();
            String code = readDoUserDto.getCode();
            if(Objects.equals(type, ReadDoTypeEnum.STA.getCode())) { // 具体人员
                readCopyTos.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.ORG.getCode())) { // 用户组织
                orgCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.ROL.getCode())) { // 用户角色
                roleCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.GROUP.getCode())) { // 用户组
                groupCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.POSITION.getCode())) { // 用户岗位
                positionCodes.add(code);
            }
        }

        // 按照类型封装
        readDoDataMap.put(ReadDoTypeEnum.STA.getCode(), readCopyTos);
        readDoDataMap.put(ReadDoTypeEnum.ORG.getCode(), orgCodes);
        readDoDataMap.put(ReadDoTypeEnum.ROL.getCode(), roleCodes);
        readDoDataMap.put(ReadDoTypeEnum.GROUP.getCode(), groupCodes);
        readDoDataMap.put(ReadDoTypeEnum.POSITION.getCode(), positionCodes);
        return readDoDataMap;
    }


    /**
     * 根据不同的数据类型和数据对象组装不同的数据
     * @param dataType
     * @param code
     * @return
     */
    public CandidateEntity convertObjectToCandidate(String dataType, String code) {
        CandidateEntity candidateEntity = new CandidateEntity();
        switch (dataType) {
            case "STA":
            case "assignee":
                candidateEntity.setCode(code);
                candidateEntity.setType("STA");
                break;
            case "ORG":
            case "ROL":
            case "GROUP":
            case "POSITION":
                candidateEntity.setCode(code);
                candidateEntity.setType(dataType);
                break;
            default:
                break;
        }
        return candidateEntity;
    }

    /**
     * 根据不同的数据类型和数据对象组装不同的数据
     * @param candidateEntitySet
     * @return
     */
    public Map<String, List<String>> convertObjectToDataMap(Set<CandidateEntity> candidateEntitySet) {
        Map<String, List<String>> dataMap = new HashMap<>();
        if(CollectionUtils.isEmpty(candidateEntitySet)) {
            return dataMap;
        }

        // 具体人员ID集合
        List<String> userIds = new ArrayList<>();

        // 阅办人所属组织集合
        List<String> orgCodes = new ArrayList<>();

        // 阅办人所属角色集合
        List<String> roleCodes = new ArrayList<>();

        // 阅办人所属用户组集合
        List<String> groupCodes = new ArrayList<>();

        // 阅办人所属岗位集合
        List<String> positionCodes = new ArrayList<>();
        for (CandidateEntity candidateEntity:candidateEntitySet) {
            String type = candidateEntity.getType();
            String code = candidateEntity.getCode();
            if(Objects.equals(type, ReadDoTypeEnum.STA.getCode())) { // 具体人员
                userIds.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.ORG.getCode())) { // 用户组织
                orgCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.ROL.getCode())) { // 用户角色
                roleCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.GROUP.getCode())) { // 用户组
                groupCodes.add(code);
            } else if(Objects.equals(type, ReadDoTypeEnum.POSITION.getCode())) { // 用户岗位
                positionCodes.add(code);
            }
        }

        // 按照类型封装
        dataMap.put(ReadDoTypeEnum.STA.getCode(), userIds);
        dataMap.put(ReadDoTypeEnum.ORG.getCode(), orgCodes);
        dataMap.put(ReadDoTypeEnum.ROL.getCode(), roleCodes);
        dataMap.put(ReadDoTypeEnum.GROUP.getCode(), groupCodes);
        dataMap.put(ReadDoTypeEnum.POSITION.getCode(), positionCodes);
        return dataMap;
    }


    /**
     * 根据不同的数据类型和数据对象组装不同的数据
     * @param dataMap
     * @return
     */
    public Set<String> resolveUserIds(Map<String, List<String>> dataMap) {
        Set<String> userIdSet = new HashSet<>();

        // 具体人ID集合
        List<String> userIds = dataMap.get(ReadDoTypeEnum.STA.getCode());

        // 阅办人所属组织集合
        List<String> orgCodes = dataMap.get(ReadDoTypeEnum.ORG.getCode());

        // 阅办人所属角色集合
        List<String> roleCodes = dataMap.get(ReadDoTypeEnum.ROL.getCode());

        // 阅办人所属用户组集合
        List<String> groupCodes = dataMap.get(ReadDoTypeEnum.GROUP.getCode());

        // 阅办人所属岗位集合
        List<String> positionCodes = dataMap.get(ReadDoTypeEnum.POSITION.getCode());

        // 如果传的不是具体的人员,则需要解析对应的类型,例如：组织、角色、岗位或用户组
        List<UserInfo> userInfos = this.resolveUserInfoList(userIds, orgCodes, roleCodes, positionCodes, groupCodes);

        // 用户信息不为空
        if(CollectionUtils.isNotEmpty(userInfos)) {

            // 类型转换
            List<String> userIdList = userInfos.stream().map(userInfo -> {
                return userInfo.getUserCode();
            }).collect(Collectors.toList());

            // 过滤重复的userId
            List<String> filterUserList = userIdList.stream().distinct().collect(Collectors.toList());
            userIdSet.addAll(filterUserList);
        }
        return userIdSet;
    }
}
